package evolutionaryProblems;

import genotype.Genotype;

import java.text.DecimalFormat;
import java.util.ArrayList;
import java.util.Collection;

public abstract class Phenotype implements Comparable<Phenotype>{
	
	protected static int phenotypeCount = 0; 
	
	protected int phenotypeID; 
	protected double fitness; 
	protected DecimalFormat decFormat = new DecimalFormat("0.000"); 
	protected boolean editable = true; 
	protected int generation = -1; 
	
	public Phenotype(){
		phenotypeID = ++phenotypeCount;
	}
	
	public double getFitness(){
		return fitness; 
	}
	
	public int compareTo(Phenotype other){
		if (other == null || this.getFitness() == other.getFitness()){
			return 0;
		} else if (this.getFitness() > other.getFitness()){
			return 1; 
		}
		return -1; 
	}
	
	public String toString(){
		if (getGeneration() != -1) {
			return "G: " + getGeneration() + "   F: " + decFormat.format(getFitness());
		}
		return decFormat.format(getFitness());
	}
	
	public abstract void calculateFitness(); 
	
	public Phenotype clone(){
		return getGenotype().clone().evolveGenotype(); 
	}
	
	public Collection<Phenotype> crossover(Phenotype other, int crossoverPoints){
		Collection<Genotype> children = this.getGenotype().crossover(other.getGenotype(), crossoverPoints); 
		return convertGenotypes(children); 
	}

	public Phenotype mutate(){
		Phenotype mutatedPhenotype = getGenotype().mutate().evolveGenotype();
		return mutatedPhenotype; 
	}
	
	protected Collection<Phenotype> convertGenotypes(Collection<Genotype> genomes){
		Collection<Phenotype> phenoms = new ArrayList<Phenotype>(genomes.size());
		for (Genotype genotype : genomes) {
			phenoms.add(genotype.evolveGenotype());
		}
		return phenoms; 
	}
	
	public Phenotype getListClone(int generation){
		Phenotype clone = getGenotype().clone().evolveGenotype(); 
		clone.setEditable(false); 
		clone.setGeneration(generation); 
		return clone; 
	}
	
	public abstract Genotype getGenotype(); 
	public abstract boolean isSolution();

	public boolean isEditable() {
		return editable;
	}

	public void setEditable(boolean editable) {
		this.editable = editable;
	}

	public int getGeneration() {
		return generation;
	}

	public void setGeneration(int generation) {
		this.generation = generation;
	}
	
	
}